package com.acegear.horizon.domain.services;

import com.acegear.horizon.domain.models.Club;
import com.acegear.horizon.domain.models.ClubEvent;
import com.acegear.horizon.domain.models.Post;
import com.acegear.horizon.domain.models.constraint.FeedType;
import com.acegear.horizon.domain.models.constraint.RecommendType;
import com.acegear.horizon.domain.models.jpa.*;
import com.acegear.horizon.domain.models.vo.ClubEventVO;
import com.acegear.horizon.domain.models.vo.FeedVO;
import com.acegear.horizon.domain.models.vo.ClubVO;
import com.acegear.horizon.domain.models.vo.UserPostVO;
import com.acegear.horizon.domain.repository.jpa.*;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;

/**
 * Created by wangsike on 2016/12/27.
 */
@Service
public class ClubService {

    @Autowired
    private ClubMemberRepository clubMemberRepository;

    @Autowired
    private RecommendRepository recommendRepository;

    @Autowired
    private ClubBaseRepository clubBaseRepository;

    @Autowired
    private UserPostRepository userPostRepository;

    @Autowired
    private ClubFeedRepository clubFeedRepository;

    @Autowired
    private ClubEventBaseRepository clubEventBaseRepository;

    public Boolean isMember(Long clubId, Long userId) {
        return clubMemberRepository.findByClubIdAndUserId(clubId, userId).isPresent();
    }

    public List<ClubVO> getClubVO(Pageable pageable, Long viewerId, RecommendType recommendType) {
        List<Recommend> recommends = recommendRepository.findByType(recommendType, pageable);
        List<Long> clubIds = recommends.stream().map(Recommend::getExternalId).collect(Collectors.toList());
        if (clubIds.isEmpty()) {
            return new ArrayList<>();
        } else {
            return clubBaseRepository
                    .findByClubIds(clubIds)
                    .stream()
                    .map(Club::new)
                    .sorted(Comparator.comparingInt(c -> clubIds.indexOf(c.getClubId())))
                    .map(club -> club.getClubVO(viewerId))
                    .collect(Collectors.toList());
        }
    }

    /**
     * 根据cludId分页查询posts
     */
    public List<UserPostVO> getPostsByClubId(Long cludId, boolean top, Pageable pageRequest, Long viewerId) {
        List<ClubFeed> clubFeeds = clubFeedRepository.findByClubIdAndFeedTypeAndTop(cludId, FeedType.USER_POST, top, pageRequest);
        //取出对应的postId集合
        List<Long> ids = clubFeeds.stream().map(ClubFeed::getRelateId).collect(Collectors.toList());
        List<UserPost> tempPosts = userPostRepository.findByDeletedAndPostIdIn(false,ids);
        List<UserPost> posts = new ArrayList<>(tempPosts.size());
        //in查找后会乱序
        for (int i = 0; i < ids.size(); i++) {
            for (int j = 0; j < tempPosts.size(); j++) {
                if (ids.get(i).equals(tempPosts.get(j).getPostId())) {
                    posts.add(tempPosts.get(j));
                }
            }
        }
        return posts.stream()
                .map(Post::new)
                .map(post -> post.getUserPostVO(viewerId))
                .collect(Collectors.toList());
    }

    /**
     * 根据cludId分页查询events
     */
    public List<ClubEventVO> getEventsByClubId(Long cludId, boolean top, Pageable pageRequest) {
        List<ClubFeed> clubFeeds = clubFeedRepository.findByClubIdAndFeedTypeAndTop(cludId, FeedType.CLUB_EVENT, top, pageRequest);
        //取出对应的clubEventId集合
        List<Long> ids = clubFeeds.stream().map(ClubFeed::getRelateId).collect(Collectors.toList());
        List<ClubEventBase> tempEvents = clubEventBaseRepository.findByClubEventIds(ids);
        List<ClubEventBase> events = new ArrayList<>(tempEvents.size());
        //in查找后会乱序
        for (int i = 0; i < ids.size(); i++) {
            for (int j = 0; j < tempEvents.size(); j++) {
                if (ids.get(i).equals(tempEvents.get(j).getClubEventId())) {
                    events.add(tempEvents.get(j));
                }
            }
        }
        return events.stream()
                .map(ClubEvent::new)
                .map(ClubEvent::getEventVO)
                .collect(Collectors.toList());
    }

    /**
     * 根据cludId分页查询feed流(包含所有的post，event等)
     */
    public List<FeedVO> getFeedByCludId(Long cludId, boolean top, Pageable pageRequest, Long viewerId) {
        //查所有的clubFeed
        List<ClubFeed> clubFeeds = clubFeedRepository.findByClubIdAndTop(cludId, top, pageRequest);
        return clubFeeds.stream()
                .map(feed -> getVO(feed, viewerId))
                .collect(Collectors.toList());
    }

    /**
     * 根据cludId分页查询feed流(除了post的)
     */
    public List<FeedVO> getFeedByCludIdWithNoPost(Long cludId, boolean top, Pageable pageRequest, Long viewerId) {
        //查所有的clubFeed
        List<ClubFeed> clubFeeds = clubFeedRepository.findByClubIdAndTopAndFeedTypeNot(cludId, top, FeedType.USER_POST, pageRequest);
        return clubFeeds.stream()
                .map(feed -> getVO(feed, viewerId))
                .collect(Collectors.toList());
    }

    private FeedVO getVO(ClubFeed clubFeed, Long viewerId) {
        //根据ClubFeedType来区分
        Long relateId = clubFeed.getRelateId();
        switch (clubFeed.getFeedType()) {
            case USER_POST:
                Optional<UserPost> userPost = userPostRepository.findByPostId(relateId);
                return userPost.map(Post::new)
                    .map(post -> post.getUserPostVO(viewerId)).get();
            case CLUB_EVENT:
                Optional<ClubEventBase> clubEvent = clubEventBaseRepository.findByClubEventId(relateId);
                return clubEvent.map(ClubEvent::new)
                        .map(ClubEvent::getEventVO).get();
            default:
                break;
        }
        return null;
    }
}
